; 使7-Zip打开看不到其他内容。
!packhdr temp.dat 'cmd /c Copy /B temp.dat /B +extra\Microld.7z temp.dat'

; 压缩率
SetCompressor /SOLID lzma
SetCompressorDictSize 32

; 提升安装程序权限(vista,win7,win8)
RequestExecutionLevel admin



; --------------------------------------------------------------------
;        <<  包含文件  >>
; --------------------------------------------------------------------
!include "x64.nsh"
!include "MUI2.nsh"
!include "FileFunc.nsh"
!include "LogicLib.nsh"
!include "WordFunc.nsh"
; Windows API
!include "WinMessages.nsh"
!include "WinCore.nsh"



; --------------------------------------------------------------------
;        <<  声明常量  >>
; --------------------------------------------------------------------
; 注册表
; Software\microld\node
; 在x64位系统下会指向 Software\Wow6432Node\microld\node
; 但不影响判断
!define GREEN_PATH_KEY "Software\microld"
!define SYSTEM_PATH_KEY "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"



; --------------------------------------------------------------------
;        <<  声明变量  >>
; --------------------------------------------------------------------
Var Microld

; 绿化变量
Var CORE_NAME
Var CORE_VERSION
Var CORE_PUBLISHER
Var CORE_WEBSITE

; 产品变量
Var PRODUCT_NAME
Var PRODUCT_VERSION

; 包管理
; package manager
Var PACKAGE_SOURCE
Var PACKAGE_VERSION

; 环境
Var ARCHITECTURE
Var PATH

; UI
Var hCtl_UI_Icon
Var hCtl_Clean_Icon

Var hCtl_UI_Title
Var hCrl_Title_Font

Var hCrl_Product_Version

Var hCrl_Group_Box
Var hCrl_Group_Line

Var hCrl_Button_Green
Var hCrl_Button_Exit

Var hCrl_Check_Source
Var hCrl_Check_Source_Status
Var hCrl_Source

Var hCrl_Check_Update
Var hCrl_Check_Update_Status

Var hCrl_Check_Other
Var hCrl_Link_Author

; 判断
Var isSoftware
Var isGreen
Var isNpm

; 透明度
Var TRANSPARENT

; --------------------------------------------------------------------
;        <<  区段  >>
; --------------------------------------------------------------------
Section
    DetailPrint "Microld"
SectionEnd



; --------------------------------------------------------------------
;        <<  脚本配置  >>
; --------------------------------------------------------------------
; 加载模板
!define MUI_UI "extra\ui.exe"

; 输出文件
OutFile "Release\Green.exe"

; 图标文件
!define MUI_ICON "extra\ico.ico"

; 标题
Name "$PRODUCT_NAME"
Caption "$(^Name)绿化"

; 语言
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro GetParameters

; 调用自定义页面
Page custom customPage



VIProductVersion "1.0.0.1009"
VIAddVersionKey /LANG=2052  "ProductName" "node绿化工具"   ;产品名称
VIAddVersionKey /LANG=2052  "Comments" "node绿化工具"  ;备注
VIAddVersionKey /LANG=2052  "CompanyName" "Microld"   ;公司
VIAddVersionKey /LANG=2052  "Microld" "http://i.qdz.me"   ;WEB
VIAddVersionKey /LANG=2052  "LegalTrademarks" "Microld"
VIAddVersionKey /LANG=2052  "LegalCopyright" "(C) 2015 Microld" ;版权
VIAddVersionKey /LANG=2052  "FileDescription" "node绿化工具" ;描述
VIAddVersionKey /LANG=2052  "FileVersion" "1.0.0"
VIAddVersionKey /LANG=2052  "OriginalFilename" "green.exe" ;源文件名



; --------------------------------------------------------------------
;        <<  预处理段  >>
; --------------------------------------------------------------------
Function .onInit

  ; 读取 产品 信息
  ReadINIStr $PRODUCT_NAME    "$EXEDIR\config.ini" "product" "name"
  ReadINIStr $PRODUCT_VERSION "$EXEDIR\config.ini" "product" "version"

  ; 读取 包管理 信息
  ReadINIStr $PACKAGE_SOURCE  "$EXEDIR\config.ini" "package" "source"
  ReadINIStr $PACKAGE_VERSION "$EXEDIR\config.ini" "package" "version"

  ; 读取绿化程序所需配置
  ReadINIStr $CORE_NAME       "$EXEDIR\config.ini" "core" "name"
  ReadINIStr $CORE_VERSION    "$EXEDIR\config.ini" "core" "version"
  ReadINIStr $CORE_PUBLISHER  "$EXEDIR\config.ini" "core" "author"
  ReadINIStr $CORE_WEBSITE    "$EXEDIR\config.ini" "core" "website"


  ; 获取界面透明度
  ReadINIStr $TRANSPARENT       "$EXEDIR\config.ini" "core" "transparent"
  ${If} $TRANSPARENT < '80'
    StrCpy $TRANSPARENT "100"
  ${EndIf}


  ; 创建互斥防止重复运行
  System::Call 'kernel32::CreateMutexA(i 0, i 0, t "autocall_installer") i .r1 ?e'
  Pop $R0
  StrCmp $R0 0 +3
    MessageBox MB_OK|MB_ICONEXCLAMATION "已经有一个绿化安装向导正在运行！ "
    Abort
  Nop
    ; 未运行多个绿化程序


  ; 系统构架
  ReadRegStr $R0 HKLM "${SYSTEM_PATH_KEY}" "PROCESSOR_ARCHITECTURE"
  StrCpy $ARCHITECTURE "x64"
  ${If} $R0 == "x86"
    StrCpy $ARCHITECTURE "x86"
  ${EndIf}


  ; 获取PATH
  ; ReadEnvStr $PATH PATH
  ReadRegStr $PATH HKLM "${SYSTEM_PATH_KEY}" "Path"


  ; 系统中是否存在NodeJS
  ; 存在 == 0 / 不存在 == error
  nsExec::Exec '"node" -v'      
  Pop $isSoftware

  ; 判断 包管理 存在
  nsExec::Exec '"npm" -v'      
  Pop $isNpm

  ; 判断是否我绿化的
  ReadRegStr $isGreen HKLM "${GREEN_PATH_KEY}\node" "name"


  ; 不考虑旧版绿化中iojs时的注册表了
  ${If} $isGreen != 'node'
    ; 存在node
    ; 通过运行node -v判断
    ${If} $isSoftware == '0'
      MessageBox MB_OK|MB_ICONEXCLAMATION "Error $\n  \
        Hello, 朋友你电脑中存在 $PRODUCT_NAME！$\n  \
        如果想安装此版本, 请先卸载原有 $PRODUCT_NAME!"
      Abort
    ${EndIf}
  ${EndIf}


  ; 判断 node 是否存在
  StrCpy $R0 "0"
  IfFileExists $EXEDIR\node\$ARCHITECTURE\node.exe 0 +2
    StrCpy $R0 "1"
  Nop
  ${If} $R0 == '0'
    MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "Error $\n  \
      文件不存在, 是否需要下载？" IDOK +2 IDCANCEL 0
    Abort
    Call Update
  ${EndIf}


  ; 判断 包管理 存在
  StrCpy $R0 "0"
  IfFileExists $EXEDIR\module\node_modules\npm\bin\npm.cmd 0 +2
    StrCpy $R0 "1"
  Nop
  ${If} $R0 == '0'
    MessageBox MB_OK|MB_ICONEXCLAMATION "Error $\n  \
      Error, 朋友你似乎把npm给删除了！"
    Abort
  ${EndIf}

FunctionEnd




; --------------------------------------------------------------------
;        <<  自定义界面  >>
; --------------------------------------------------------------------
Function customPage
  nsDialogs::Create 1018

  ; 透明
  IntOp $R8 $TRANSPARENT * 255
  IntOp $R8 $R8 / 100
  System::Call "user32::SetWindowPos(i $HWNDPARENT, i -1, i0, i0, i0, i0, i 3)"
  StrCpy $R2 $R8  ;透明度（0-255）
  System::Call 'User32::GetWindowLong(i $HWNDPARENT, i -20) .iR0'
  IntOp $R0 $R0 + 0x80000
  System::Call 'User32::SetWindowLong(i $HWNDPARENT, i -20, i R0) .iR1'
  System::Call 'User32::SetLayeredWindowAttributes(i $HWNDPARENT, i 0, i R2, i 2) .i R0'


  ; 隐藏最大化 & 最小化
  System::Call 'user32::GetWindowLong(i $hwndparent,i -16)i.r0'
  intop $1 0x30000 ~
  intop $0 $0 & $1
  System::Call 'user32::SetWindowLong(i $hwndparent,i -16,i $0)i' ;最大化不可用

  Pop $Microld
  ${If} $Microld == error
  Abort
  ${EndIf}


  ; === Icon ===
  ${NSD_CreateIcon} 6u 1u 21u 19u ""
  Pop $hCtl_UI_Icon
  File "/oname=$PLUGINSDIR\ICO.ico" "extra\ICO.ico"
  ${NSD_SetIcon} $hCtl_UI_Icon "$PLUGINSDIR\ICO.ico" $hCtl_Clean_Icon
  ${NSD_FreeImage} $hCtl_Clean_Icon


  ; === Label : Title  ===
  ${NSD_CreateLabel}  33u 1u 93u 19u "$PRODUCT_NAME $CORE_NAME"
  Pop $hCtl_UI_Title
  CreateFont $hCrl_Title_Font "Microsoft JhengHei" "12" "700"
  SendMessage $hCtl_UI_Title ${WM_SETFONT} $hCrl_Title_Font 0
  SetCtlColors $hCtl_UI_Title 0x3399FF transparent

  ; === Label : Product  ===
  ${NSD_CreateLabel}  33u 16u 93u 9u "$PRODUCT_NAME $PRODUCT_VERSION"
  Pop $hCrl_Product_Version

  ; === GroupBox : Box  ===
  ${NSD_CreateGroupbox} 3u 22u 126u 64u ""
  Pop $hCrl_Group_Box

  ; === GroupBox : Line  ===
  ${NSD_CreateGroupbox} 1u 88u 128u 5u ""
  Pop $hCrl_Group_Line

  ; === Button : Exit ===
  ${NSD_CreateButton} 74u 96u 49u 13u "退出"
    Pop $hCrl_Button_Exit
    ${NSD_OnClick} $hCrl_Button_Exit Exit


  ; === Button : Green && Unstall ===
  ${NSD_CreateButton} 14u 30u 104u 19u "卸载"
    Pop $hCrl_Button_Green
    EnableWindow $hCrl_Button_Green 0

  ${If} $isSoftware == '0' ; 系统中存在node
    ${if} $isGreen == 'node' ; 是我绿化的
      SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:卸载"
      EnableWindow $hCrl_Button_Green 1
      ${NSD_OnClick} $hCrl_Button_Green uInstall
    ${EndIf}
  ${Else}  ; 系统中不存在node
    SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:绿化"
    EnableWindow $hCrl_Button_Green 1
    Pop $hCrl_Button_Green
    ${NSD_OnClick} $hCrl_Button_Green Install
  ${EndIf}

  Pop $hCrl_Button_Green
  CreateFont $R0 "宋体" "10" "500"
  SendMessage $hCrl_Button_Green ${WM_SETFONT} $R0 0


  ; === CheckBox : Source ===
  ${NSD_CreateCheckBox} 18u 52u 104u 11u "更改包源为淘宝源"
    Pop $hCrl_Check_Update
    EnableWindow $hCrl_Check_Update 0

  ; === CheckBox : Update ===
  ${NSD_CreateCheckBox} 18u 62u 104u 11u "更新到最新版本"
    Pop $hCrl_Check_Source
    EnableWindow $hCrl_Check_Source 0

  ; === CheckBox : UNLL ===
  ${NSD_CreateCheckBox} 18u 72u 104u 11u "预留"
    Pop $hCrl_Check_Other
    EnableWindow $hCrl_Check_Other 0

  ; === Link : About ===
  ${NSD_CreateLink} 8u 98u 30u 9u "Microld"
    Pop $hCrl_Link_Author
    ${NSD_OnClick} $hCrl_Link_Author myUrl

  nsDialogs::Show
FunctionEnd


Function uInstall

  Call ReadEnv

  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:卸载中..."

  ; 获取$PATH
  FileOpen $R0 $TEMP\path w
  FileWrite $R0 "$PATH"
  FileWrite $R0 "$\r$\n"
  FileClose $R0

  ; 获取node PATH
  ReadRegStr $R6 HKLM "${GREEN_PATH_KEY}\node" "path"
  ; 移除字符
  Push "$R6;"
  Push ""
  Push all
  Push all
  Push $TEMP\path
  Call AdvReplaceInFile

  ReadRegStr $R6 HKLM "${GREEN_PATH_KEY}\node" "path"
  ; 移除字符
  Push "$R6"
  Push ""
  Push all
  Push all
  Push $TEMP\path
  Call AdvReplaceInFile


  ; 获取npm PATH
  ReadRegStr $R7 HKLM "${GREEN_PATH_KEY}\node\npm"  "path"
  ; 移除字符
  Push "$R7;"
  Push ""
  Push all
  Push all
  Push $TEMP\path
  Call AdvReplaceInFile

  ReadRegStr $R7 HKLM "${GREEN_PATH_KEY}\node\npm"  "path"
  ; 移除字符
  Push "$R7"
  Push ""
  Push all
  Push all
  Push $TEMP\path
  Call AdvReplaceInFile

  FileOpen $R0 $TEMP\path r
    FileRead $R0 $R1
  FileClose $R0

  WriteRegStr HKLM "${SYSTEM_PATH_KEY}" "path" "$R1"
  DeleteRegValue HKLM "${SYSTEM_PATH_KEY}" "npm_path"
  DeleteRegValue HKLM "${SYSTEM_PATH_KEY}" "node_path"

  DeleteRegKey HKLM "${GREEN_PATH_KEY}"


  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment"


  Delete $TEMP\path

  MessageBox MB_OK|MB_ICONEXCLAMATION "卸载完成"

  
  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:绿化"
  ${NSD_OnClick} $hCrl_Button_Green Install
  EnableWindow $hCrl_Check_Source 0
FunctionEnd

Function Install

  Call ReadEnv

  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:绿化中..."
  
  ; 获取环境变量
  ; Call ReadEnv
  
  ; 环境注册表
  WriteRegStr HKLM "${SYSTEM_PATH_KEY}"        "node_home"     "$EXEDIR\node\$ARCHITECTURE"
  WriteRegStr HKLM "${SYSTEM_PATH_KEY}"        "npm_home"      "$EXEDIR\module"
  WriteRegStr HKLM "${SYSTEM_PATH_KEY}"        "path"          "$PATH;$EXEDIR\node\$ARCHITECTURE;$EXEDIR\module;"


  ; node
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node"    "name"          "$PRODUCT_NAME"
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node"    "version"       "$PRODUCT_VERSION"
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node"    "path"          "$EXEDIR\node\$ARCHITECTURE"


  ; npm
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node\npm"     "path"          "$EXEDIR\module"


  ; 刷新注册表
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment"
  ;SendMessage ${HWND_BROADCAST} ${WM_SETTINGCHANGE} 0 "STR:Environment"

  ; 备份文件
  IfFileExists $EXEDIR\module\node_modules\npm\npmrc 0 +2
    Rename $EXEDIR\module\node_modules\npm\npmrc $EXEDIR\npm\node_modules\npm\npmrc_backup
  Nop

  ; 写文件
  FileOpen $R0 $EXEDIR\module\node_modules\npm\npmrc w
    FileWrite $R0 "prefix=$EXEDIR\module$\r$\n"
    FileWrite $R0 "cache=$EXEDIR\cache$\r$\n"
  ${If} $PACKAGE_SOURCE == "taobao"
    FileWrite $R0 "registry=http://registry.npm.taobao.org/"
  ${Else}
    FileWrite $R0 "registry=http://registry.npmjs.org/"
  ${EndIf}
  FileClose $R0


  MessageBox MB_OK|MB_ICONEXCLAMATION "绿化完成"


  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:卸载"
    ${NSD_OnClick} $hCrl_Button_Green uInstall
    EnableWindow $hCrl_Check_Source 1

FunctionEnd



Function Update

  ; 7za e v3.3.0.zip -o./npm -y
  ; aria2c -c -d <path> -o <rename> http://npm.taobao.org/mirrors/node/v4.1.2/win-x64/node.exe
  ; aria2c -c -d <path> -o <rename> http://npm.taobao.org/mirrors/node/v4.1.2/win-x86/node.exe

  ; aria2c -c -d <path> -o <rename> http://nodejs.org/dist/v4.1.2/win-x86/node.exe
  ; aria2c -c -d <path> -o <rename> http://nodejs.org/dist/v4.1.2/win-x64/node.exe


  ; http://npm.taobao.org/mirrors/npm/v2.14.6.zip
  ; http://npm.taobao.org/mirrors/npm/v2.14.7.zip
  ; http://npm.taobao.org/mirrors/npm/v3.3.6.zip

  ; https://github.com/npm/npm/archive/v2.14.6.zip
  ; https://github.com/npm/npm/archive/v2.14.7.zip
  ; https://github.com/npm/npm/archive/v3.3.6.zip

  ; CreateDirectory $INSTDIR\backup
  ; File "/oname=$PLUGINSDIR\ICO.ico" "ICO.ico"
  ; File "/oname=<输出>" "<输入>"

  SetOutPath "$TEMP\Green"
  File /r "extra\curl\curl.exe"
  File /r "extra\7z.exe"

  nsExec::Exec '"$TEMP\aria2c.exe" -c -d "$EXEDIR\node\x64" "http://npm.taobao.org/mirrors/node/$PRODUCT_VERSION/win-x64/node.exe"'
  nsExec::Exec '"$TEMP\aria2c.exe" -c -d "$EXEDIR\node\x86" "http://npm.taobao.org/mirrors/node/$PRODUCT_VERSION/win-x86/node.exe"'




  nsExec::Exec '"$TEMP\aria2c.exe" -c -d "$EXEDIR\module\node_modules" "http://npm.taobao.org/mirrors/npm/$PACKAGE_VERSION.zip"'
  nsExec::Exec '"$TEMP\7z.exe" x "$EXEDIR\module\node_modules\$PACKAGE_VERSION.zip" -o"$EXEDIR\module\node_modules" -y -aos'

  ;要移除$PACKAGE_VERSION中的v
  ; $PACKAGE_VERSION = v3.3.8
  ;移除后3.3.8
  ; 目前找到可供参考
  ; http://blog.csdn.net/foxbryant/article/details/17245247
  ${WordReplace} $PACKAGE_VERSION "v" "" "+" $R0
  Rename "$EXEDIR\module\node_modules\npm-$R0" "$EXEDIR\module\node_modules\npm"
  CopyFiles "$EXEDIR\module\node_modules\npm\bin\npm.cmd" "$EXEDIR\module\npm.cmd"
  CopyFiles "$EXEDIR\module\node_modules\npm\bin\npm" "$EXEDIR\module\npm"
  Delete "$EXEDIR\module\node_modules\$PACKAGE_VERSION.zip"

FunctionEnd




Function Exit
  MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "Hello $\n  \
      朋友你确定要关闭我！" IDOK 0 IDCANCEL +2
    sendmessage $HWNDPARENT ${wm_close} 0 0
  Nop
FunctionEnd


Function myUrl
  ExecShell "open" "$CORE_WEBSITE"
FunctionEnd


Function ReadEnv

  ; 读取 产品 信息
  ReadINIStr $PRODUCT_NAME    "$EXEDIR\config.ini" "product" "name"
  ReadINIStr $PRODUCT_VERSION "$EXEDIR\config.ini" "product" "version"

  ; 读取 包管理 信息
  ReadINIStr $PACKAGE_SOURCE  "$EXEDIR\config.ini" "package" "source"
  ReadINIStr $PACKAGE_VERSION "$EXEDIR\config.ini" "package" "version"


  ; 系统构架
  ReadRegStr $R0 HKLM "${SYSTEM_PATH_KEY}" "PROCESSOR_ARCHITECTURE"
  StrCpy $ARCHITECTURE "x64"
  ${If} $R0 == "x86"
    StrCpy $ARCHITECTURE "x86"
  ${EndIf}


  ; 获取PATH
  ; ReadEnvStr $PATH PATH
  ReadRegStr $PATH HKLM "${SYSTEM_PATH_KEY}" "Path"


  ; 系统中是否存在NodeJS
  ; 存在 == 0 / 不存在 == error
  nsExec::Exec '"node" -v'      
  Pop $isSoftware


  ; 判断是否我绿化的
  ReadRegStr $isGreen HKLM "${GREEN_PATH_KEY}" "name"


  ; 判断 包管理 存在
  nsExec::Exec '"npm" -v'      
  Pop $isNpm

FunctionEnd




Function AdvReplaceInFile
  Exch $0 ;file to replace in
  Exch
  Exch $1 ;number to replace after
  Exch
  Exch 2
  Exch $2 ;replace and onwards
  Exch 2
  Exch 3
  Exch $3 ;replace with
  Exch 3
  Exch 4
  Exch $4 ;to replace
  Exch 4
  Push $5 ;minus count
  Push $6 ;universal
  Push $7 ;end string
  Push $8 ;left string
  Push $9 ;right string
  Push $R0 ;file1
  Push $R1 ;file2
  Push $R2 ;read
  Push $R3 ;universal
  Push $R4 ;count (onwards)
  Push $R5 ;count (after)
  Push $R6 ;temp file name
   
    GetTempFileName $R6
    FileOpen $R1 $0 r ;file to search in
    FileOpen $R0 $R6 w ;temp file
     StrLen $R3 $4
     StrCpy $R4 -1
     StrCpy $R5 -1
   
  loop_read:
   ClearErrors
   FileRead $R1 $R2 ;read line
   IfErrors exit
   
     StrCpy $5 0
     StrCpy $7 $R2
   
  loop_filter:
     IntOp $5 $5 - 1
     StrCpy $6 $7 $R3 $5 ;search
     StrCmp $6 "" file_write1
     StrCmp $6 $4 0 loop_filter
   
  StrCpy $8 $7 $5 ;left part
  IntOp $6 $5 + $R3
  IntCmp $6 0 is0 not0
  is0:
  StrCpy $9 ""
  Goto done
  not0:
  StrCpy $9 $7 "" $6 ;right part
  done:
  StrCpy $7 $8$3$9 ;re-join
   
  IntOp $R4 $R4 + 1
  StrCmp $2 all loop_filter
  StrCmp $R4 $2 0 file_write2
  IntOp $R4 $R4 - 1
   
  IntOp $R5 $R5 + 1
  StrCmp $1 all loop_filter
  StrCmp $R5 $1 0 file_write1
  IntOp $R5 $R5 - 1
  Goto file_write2
   
  file_write1:
   FileWrite $R0 $7 ;write modified line
  Goto loop_read
   
  file_write2:
   FileWrite $R0 $R2 ;write unmodified line
  Goto loop_read
   
  exit:
    FileClose $R0
    FileClose $R1
   
     SetDetailsPrint none
    Delete $0
    Rename $R6 $0
    Delete $R6
     SetDetailsPrint both
   
  Pop $R6
  Pop $R5
  Pop $R4
  Pop $R3
  Pop $R2
  Pop $R1
  Pop $R0
  Pop $9
  Pop $8
  Pop $7
  Pop $6
  Pop $5
  Pop $0
  Pop $1
  Pop $2
  Pop $3
  Pop $4
FunctionEnd